package com.fyyg.wechat.util.wechat;

import java.util.Date;
import java.util.Map;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fyyg.common.exceptions.StandardException;
import com.fyyg.wechat.util.HttpClientUtils;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;

public class WechatUtils {

	static Logger log = Logger.getLogger(WechatUtils.class);
	private static String appid = "wxf0886049e5d5eb02";
	private static String secret = "252e7b9a6242c37e6ff8cf64cf0cfcd9";
	
	private static String accessTokenApi="https://api.weixin.qq.com/sns/oauth2/access_token";
	private static String requestCharset="UTF-8";
	private static String responseCharset="UTF-8";
	private static Integer connectTimeout=2000;
	private static Integer serviceTimeout=30000;
	private static String lang="zh_CN";
	
	private static String refreshTokenApi = "https://api.weixin.qq.com/sns/oauth2/refresh_token";
	
	private static String authApi = "https://api.weixin.qq.com/sns/auth";
	
	private static String userinfoApi="https://api.weixin.qq.com/sns/userinfo";
	
	private static String ticketApi = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=$ACCESS_TOKEN&type=jsapi";
	
	private static String clientCredentialApi = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$APPID&secret=$APPSECRET";
	
	private static String wechatUrlJsapiSignTextApi = "jsapi_ticket=$jsapiTicket&noncestr=$noncestr&timestamp=$timestamp&url=$url";
	
	private static String wechat_domain = "";
	
	public static String uri = "/index/index.jthml";
	
	public static void main(String[] args) {
//		appID
//		wxf0886049e5d5eb02
//		appsecret
//		8596778973d6f9087e26d6e858001359
		String appid = "";
		String secret = "";
		String code = "";
//		AccessToken accessToken = doAccessToken(code,appid,secret);
//		UserInfo userInfo = doUserinfo(accessToken.getAccessToken(), accessToken.getOpenid());
		//以后存储微信用户信息
		ShareSecondary shareSecondary = new ShareSecondary();
		shareSecondary = getShareSecondary(uri,"",shareSecondary);
		System.out.println(JSON.toJSONString(shareSecondary));
	}
	
	public AccessToken auth(String accessToken, String openId)
			throws StandardException {
		return doAuth(accessToken, openId);
	}
	
	protected AccessToken doAuth(String accessToken, String openId)
			throws StandardException {
		Map<String, String> maps = Maps.newHashMap();
		maps.put("access_token", accessToken);
		maps.put("openId", openId);

		return doRemote(authApi, maps, AccessToken.class);
	}

	public UserInfo userinfo(String accessToken, String openId)
			throws StandardException {
		return doUserinfo(accessToken, openId);
	}
	
	public AccessToken accessToken(String code){
		AccessToken accessToken = doAccessToken(code, appid, secret);
		return accessToken;
	}
	
	public AccessToken refreshToken(String refreshToken,String appTag)
			throws StandardException {
		return doRefreshToken(refreshToken, appid, secret);
	}
	
	protected AccessToken doRefreshToken(String refreshToken, String appid,
			String secret) throws StandardException {
		Map<String, String> maps = Maps.newHashMap();
		maps.put("appid", appid);
		maps.put("refresh_token", refreshToken);
		maps.put("grant_type", "refresh_token");

		return doRemote(refreshTokenApi, maps, AccessToken.class);
	}
	
	public static String loadJsApiTicket(String wechatPublicAppid,String publicSecretKey) {
		String accessToken = getAssToken(wechatPublicAppid,publicSecretKey);
		JSONObject param = new JSONObject();
		param.put("ACCESS_TOKEN", accessToken);
		String jsapiNew = VelocityHelper.buildVelocityContent(ticketApi, param);
		log.info("你好");
		log.info("【jsapiNew】"+jsapiNew);
		return jsapiNew;
	}
	
	public static String getAssToken(String wechatPublicAppid,String publicSecretKey) {
		String accessToken = WechatRedis.getClientCredential(wechatPublicAppid);
		if (!Strings.isNullOrEmpty(accessToken)) {
			return accessToken;
		}
		JSONObject param = new JSONObject();
		param.put("APPID", wechatPublicAppid);
		param.put("APPSECRET", publicSecretKey);
		AccessToken token = doRemote(VelocityHelper.buildVelocityContent(clientCredentialApi, param), null, AccessToken.class);
		log.info("【微信获取accessToken】"+JSON.toJSONString(accessToken));
		String newAccessToken = token.getAccessToken();
		WechatRedis.setClientCredential(wechatPublicAppid, newAccessToken,
				token.getExpiresIn());
		return newAccessToken;
	}
	
	public static ShareSecondary getShareSecondary(String uri, String urlParm,ShareSecondary shareSecondary) {
		ShareSecondary result = new ShareSecondary();
		JsConfig jsConfig = getJsConfig(uri,urlParm);
		result.setTitle(shareSecondary.getTitle());
		result.setContent(shareSecondary.getContent());
		result.setImage(shareSecondary.getImage());
		result.setShareurl(shareSecondary.getShareurl());
		
		result.setAppid(jsConfig.getAppId());
		result.setNoncestr(jsConfig.getNonceStr());
		result.setSignature(jsConfig.getSignature());
		result.setTimestamp(jsConfig.getTimestamp());
		
		return result;
	}
	
	public static JsConfig getJsConfig(String uri, String urlParm) {
		
		JsConfig jsConfig = new JsConfig();
		String noncestr = RandomStringUtils.randomAlphanumeric(12);
		String timestamp = String
				.valueOf(new Date().getTime() / 1000);
		String jsApiTicket = loadJsApiTicket(appid, secret);
		log.error("【jsApiTicket】"+jsApiTicket);
//		String jsapiTicket =  WechatUtils.getJsApiTicket();
		JSONObject param = new JSONObject();
		param.put("jsapiTicket", jsApiTicket);
		param.put("noncestr", noncestr);
		param.put("timestamp", timestamp);
		param.put("url", uri);
		String signText = VelocityHelper.buildVelocityContent(wechatUrlJsapiSignTextApi, param);
//		String urlParm = "";
//		String url = WechatUtils.getAccessUrl(uri, urlParm);
		
		String signature = DigestUtils.sha1Hex(signText);
		jsConfig.setAppId(appid);
		jsConfig.setNonceStr(noncestr);
		jsConfig.setSignature(signature);
		jsConfig.setTimestamp(timestamp);
		return jsConfig;
		
	}
	
	public static String getAccessUrl(String uri,String urlParm) {
		StringBuffer access = processBaseParam(uri, urlParm, wechat_domain);
		return access.toString();
	}
	
	private static StringBuffer processBaseParam(String uri,String urlParm,
			String domain) {
		StringBuffer access = new StringBuffer();
		access.append(domain);
		access.append(uri);
		if(StringUtils.isNotEmpty(urlParm)){
			access.append("?");
			access.append(urlParm);
		}
		return access;
	}
	
	private static <T extends WechatResult> T doRemote(String url,
			Map<String, String> maps, Class<T> clz) {

		String res = null;
		try {
			res = HttpClientUtils.doGet(url, maps, requestCharset,
					responseCharset, connectTimeout, serviceTimeout);
		} catch (Throwable e) {
			throw e;
		}
		T t = JSON.parseObject(res, clz);
		parseException(t);
		return t;

	}
	
	public static AccessToken doAccessToken(String code, String appid, String secret) {
		Map<String, String> maps = Maps.newHashMap();
		maps.put("appid", appid);
		maps.put("secret", secret);
		maps.put("code", code);
		maps.put("grant_type", "authorization_code");
		return doRemote(accessTokenApi, maps, AccessToken.class);
	}
	
	
	
	public static UserInfo doUserinfo(String accessToken, String openId)
			throws StandardException {
		Map<String, String> maps = Maps.newHashMap();
		maps.put("access_token", accessToken);
		maps.put("openId", openId);
		maps.put("lang", lang);

		return doRemote(userinfoApi, maps, UserInfo.class);
	}
	
	private static void parseException(WechatResult wechatResult) {
		String errorCode = wechatResult.getErrcode();
		if (Strings.isNullOrEmpty(errorCode) || "0".equals(errorCode)) {
			return;
		}
		throw new StandardException(wechatResult.getErrcode(),wechatResult.getErrmsg(),null);
	}
}
